package it.koutifaris.travianmap.dal.sqlservices.tile;

import static it.koutifaris.testforclassutils.IsTestForAssert.assertIsTestFor;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import it.koutifaris.travianmap.dal.RevisionService.Revision;
import it.koutifaris.travianmap.dal.sqlservices.AbstractMapDbTest;
import it.koutifaris.travianmap.dal.sqlservices.dumpimporter.TravianSqlDumpImporter;
import it.koutifaris.travianmap.mapsqlparser.MapSqlEntry;
import it.koutifaris.travianmap.model.Alliance;
import it.koutifaris.travianmap.model.Player;
import it.koutifaris.travianmap.model.Tribe;
import it.koutifaris.travianmap.model.Village;
import it.koutifaris.travianmap.tile.Tile;
import it.koutifaris.travianmap.utils.DayTruncUtils;

import java.util.Date;

import junit.framework.Assert;

public class SqlTileLoaderTest extends AbstractMapDbTest {

	private SqlTileLoader tileLoader;
	private Revision testRevision;

	@Override
	protected void overridableSetUp() {
		testRevision = mockRevision(new Date());
		createOneEntryDB();
		tileLoader = new SqlTileLoader(SERVER_ID, getDbHelper().getReadableDatabase(), testRevision);
	}

	public void testPkgAndName() {
		assertIsTestFor(SqlTileLoader.class);
	}

	public void testGetNumberOfVillages() {
		Tile tile = tileLoader.loadTileAt(OneEntryData.VILLAGE_X, OneEntryData.VILLAGE_Y);
		Assert.assertEquals(1, tile.getNumberOfVillages());
	}

	public void testVillageData() {
		Tile tile = tileLoader.loadTileAt(OneEntryData.VILLAGE_X, OneEntryData.VILLAGE_Y);
		Village village = getVillageFromTile(tile);

		Assert.assertEquals(OneEntryData.VILLAGE_ID, village.getElementId());
		Assert.assertEquals(OneEntryData.VILLAGE_NAME, village.getName());
		Assert.assertEquals(OneEntryData.VILLAGE_POPULATION, village.getPopulation());
		Assert.assertEquals(OneEntryData.VILLAGE_X, village.getX());
		Assert.assertEquals(OneEntryData.VILLAGE_Y, village.getY());
	}

	public void testPlayerData() {
		Tile tile = tileLoader.loadTileAt(OneEntryData.VILLAGE_X, OneEntryData.VILLAGE_Y);
		Player player = getVillageFromTile(tile).getOwner();

		Assert.assertEquals(OneEntryData.PLAYER_ID, player.getElementId());
		Assert.assertEquals(OneEntryData.PLAYER_NAME, player.getName());
		Assert.assertEquals(Tribe.valueOf(OneEntryData.TRIBE_ID), player.getTribe());
	}

	public void testAllianceData() {
		Tile tile = tileLoader.loadTileAt(OneEntryData.VILLAGE_X, OneEntryData.VILLAGE_Y);
		Alliance alliance = getVillageFromTile(tile).getOwner().getAlliance();

		Assert.assertEquals(OneEntryData.ALLIANCE_ID, alliance.getElementId());
		Assert.assertEquals(OneEntryData.ALLIANCE_NAME, alliance.getName());
	}

	private Village getVillageFromTile(Tile tile) {
		Iterable<Village> villages = tile.getVillages();
		Village village = villages.iterator().next();
		return village;
	}

	private void createOneEntryDB() {
		TravianSqlDumpImporter importer = new TravianSqlDumpImporter(getDbHelper().getWritableDatabase());

		importer.init(testRevision.getDay());
		importer.onEntry(mockSqlEntry());
		importer.done();
	}

	private Revision mockRevision(Date day) {
		Revision revision = mock(Revision.class);

		Date truncedDay = DayTruncUtils.truncDateToDay(day);

		when(revision.getId()).thenReturn(truncedDay.getTime());
		when(revision.getDay()).thenReturn(truncedDay);

		return revision;
	}

	private MapSqlEntry mockSqlEntry() {
		final MapSqlEntry mockedEntry = mock(MapSqlEntry.class);

		when(mockedEntry.getSquareId()).thenReturn(OneEntryData.SQUARE_ID);
		when(mockedEntry.getX()).thenReturn(OneEntryData.VILLAGE_X);
		when(mockedEntry.getY()).thenReturn(OneEntryData.VILLAGE_Y);
		when(mockedEntry.getTribeId()).thenReturn(OneEntryData.TRIBE_ID);
		when(mockedEntry.getVillageId()).thenReturn(OneEntryData.VILLAGE_ID);
		when(mockedEntry.getVillageName()).thenReturn(OneEntryData.VILLAGE_NAME);
		when(mockedEntry.getPlayerId()).thenReturn(OneEntryData.PLAYER_ID);
		when(mockedEntry.getPlayerName()).thenReturn(OneEntryData.PLAYER_NAME);
		when(mockedEntry.getAllianceId()).thenReturn(OneEntryData.ALLIANCE_ID);
		when(mockedEntry.getAllianceName()).thenReturn(OneEntryData.ALLIANCE_NAME);
		when(mockedEntry.getVillagePopulation()).thenReturn(OneEntryData.VILLAGE_POPULATION);

		return mockedEntry;
	}

	private static class OneEntryData {
		private static final int SQUARE_ID = 754;
		private static final int VILLAGE_ID = 120516;
		private static final int VILLAGE_Y = 400;
		private static final int VILLAGE_X = 353;
		private static final String VILLAGE_NAME = "-R2-Susina";
		private static final int VILLAGE_POPULATION = 25;
		private static final int TRIBE_ID = 2;
		private static final String ALLIANCE_NAME = "SOLI";
		private static final int ALLIANCE_ID = 1347;
		private static final String PLAYER_NAME = "nathan";
		private static final int PLAYER_ID = 10852;
	}
}
